home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 November: Tool Chest / Dev.CD Nov 98 TC.toast / Sample Code / Sound / A-Law sdec⁄scom / Common.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-06-18  |  9.7 KB  |  237 lines  |  [TEXT/CWIE]

  1. /*
  2. **    Apple Macintosh Developer Technical Support
  3. **
  4. **    Routines common to a sound decompressor and compressor.
  5. **
  6. **    by Mark Cookson, Apple Developer Technical Support
  7. **
  8. **    File:    Common.c
  9. **
  10. **    Copyright ©1996 Apple Computer, Inc.
  11. **    All rights reserved.
  12. **
  13. **    You may incorporate this sample code into your applications without
  14. **    restriction, though the sample code has been provided "AS IS" and the
  15. **    responsibility for its operation is 100% yours.  However, what you are
  16. **    not permitted to do is to redistribute the source as "Apple Sample
  17. **    Code" after having made changes. If you're going to re-distribute the
  18. **    source, we require that you make it clear in the source that the code
  19. **    was descended from Apple Sample Code, but that you've made changes.
  20. */
  21.  
  22. #define kSoundComponentVersion            0x00010000        // version for this sound component
  23. #define kRequiredSndMgrMajorRev            3                // Sound Manager version required to run this component
  24.  
  25. #define kOutputSampleSize                16                // output sample size
  26.  
  27. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  28. // Call in the component dispatcher code
  29. //
  30. // Main Component Entry Point is the component dispacher code
  31. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  32. #include "ComponentDispatch.c"                            
  33.  
  34. #if !GENERATINGPOWERPC
  35. //----------------------------------------------------------------------------------
  36. // main
  37. //----------------------------------------------------------------------------------
  38. pascal ComponentResult main( ComponentParameters *params, SoundComponentGlobalsPtr globals );
  39. pascal ComponentResult main( ComponentParameters *params, SoundComponentGlobalsPtr globals )
  40. {
  41.     return (SoundComponentEntryPoint(params,globals));
  42. }
  43. #endif
  44.  
  45. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  46. // Component Manager Methods
  47. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  48. /*    ==============================================================================
  49.     Component Open
  50.  
  51.     This routine is called when the Component Manager creates an instance of this
  52.     component. The routine should allocate global variables in the appropriate heap
  53.     and call SetComponentInstanceStorage() so the Component Manager can remember
  54.     the globals and pass them to all the method calls.
  55.     
  56.     Determining the heap to use can be tricky. The Component Manager will normally
  57.     load the component code into the system heap, which is good, since many applications
  58.     will be sharing this component to play sound. In this case, the components's global
  59.     variable storage should also be created in the system heap.
  60.  
  61.     However, if system heap memory is tight, the Component Manager will load
  62.     the component into the application heap of the first application that plays sound.
  63.     When this happens, the component should create global storage in the application heap
  64.     instead. The Sound Manager will make sure that other applications will not try
  65.     to play sound while the component is in this application heap.
  66.  
  67.     To determine the proper heap to use, call GetComponentInstanceA5(). If the value
  68.     returned is 0, then the component was loaded into the system heap, and all storage
  69.     should be allocated there. If the value returned is non-zero, the component is in
  70.     the application heap specifed by returned A5 value, and all storage should be
  71.     allocated in this application heap.
  72.     
  73.     NOTE: If the component is loaded into the application heap, the value returned by
  74.     GetComponentRefCon() will be 0.
  75.     NOTE: Do not attempt to initialize in this call, since the Component Manager will
  76.     call Open() BEFORE calling Register().
  77.     NOTE: This routine is never called at interrupt time.
  78.     ============================================================================== */
  79.  
  80. pascal ComponentResult __SoundComponentOpen(void *unused1, ComponentInstance self)
  81. {
  82. #pragma unused (unused1)
  83.  
  84.     Handle            h;
  85.     SoundComponentGlobalsPtr        globals;
  86.  
  87.     h = NewHandleClear(sizeof(SoundComponentGlobals));        // get space for globals
  88.     if (h == nil)
  89.         return(MemError());
  90.  
  91.     HLock(h);
  92.     globals = (SoundComponentGlobalsPtr) *h;
  93.     SetComponentInstanceStorage (self, (Handle) globals);     // save pointer to our globals
  94.  
  95.     globals->globalsHandle = h;                                // remember the handle
  96.     globals->thisComponent.format = kOutputSampleFormat;    // output sample format
  97.     globals->thisComponent.sampleSize = kOutputSampleSize;    // output sample size
  98.     globals->outputSamples = kMaxOutputSamples;                // size of our output buffer
  99.  
  100.     return (noErr);
  101. }
  102.  
  103. /*    ==============================================================================
  104.     Component Close
  105.  
  106.     This routine is called when the Component Manager is closing the instance of
  107.     this component. It should delete all global storage and close any other components
  108.     that were opened.
  109.     
  110.     NOTE: Be sure to check that the globals pointer passed in to this routine is
  111.     not set to NIL. If the Open() routine fails for any reason, the Component
  112.     Manager will call this routine passing in a NIL for the globals.
  113.     NOTE: This routine is never called at interrupt time.
  114.     ============================================================================== */
  115.  
  116. pascal ComponentResult __SoundComponentClose(SoundComponentGlobalsPtr globals, ComponentInstance self)
  117. {
  118. #pragma unused (self)
  119.  
  120.     if (globals)                                            // we have some globals
  121.     {
  122.         if (globals->sourceComponent)                        // we have a source component
  123.             CloseComponent(globals->sourceComponent);        // close it
  124.     
  125.         globals->thisComponent.sampleCount = 0;                // nothing in our buffer now
  126.         DisposeHandle(globals->globalsHandle);                // dispose our storage
  127.     }
  128.  
  129.     return (noErr);
  130. }
  131.  
  132. /*    ==============================================================================
  133.     Component Register
  134.  
  135.     This routine is called once, usually at boot time, when the Component Manager
  136.     is first registering this sound component. This routine should check to see if the proper
  137.     Sound Manager is installed and return 0 if it is. If the right Sound Manager is not
  138.     installed, the routine should return 1 and this component will not be registered.
  139.  
  140.     NOTE: The cmpWantsRegisterMessage bit must be set in the component flags of the
  141.     sound component in order for this routine to be called.
  142.     NOTE: This routine is never called at interrupt time.
  143.     ============================================================================== */
  144.  
  145. pascal ComponentResult __SoundComponentRegister(SoundComponentGlobalsPtr globals)
  146. {
  147. #pragma unused (globals)
  148.  
  149.     long        result;
  150.     NumVersion    version;
  151.  
  152.     if ((Gestalt(gestaltSoundAttr, &result) == noErr) &&        // snd gestalt is available
  153.         (result & (1L << gestaltSoundIOMgrPresent)))            // snd dispatcher is available
  154.     {
  155.         version = SndSoundManagerVersion();                        // get the Sound Manager version
  156.         if (version.majorRev >= kRequiredSndMgrMajorRev)        // it's what we need
  157.         {
  158.             return (0);                                            // install this compression component
  159.         }
  160.     }
  161.     
  162.     return (1);                                                    // do not install component
  163. }
  164.  
  165. /*    ==============================================================================
  166.     GetInfo
  167.  
  168.     This routine returns information about this output component to the Sound Manager.
  169.     A 4-byte OSType selector is used to determine the type and size of the information
  170.     to return. If the component does not support a selector, it should delegate this
  171.     call on up the chain.
  172.  
  173.     NOTE: This can be called at interrupt time. However, selectors that return
  174.     a handle will not be called at interrupt time.
  175.     ============================================================================== */
  176.  
  177. pascal ComponentResult __SoundComponentGetInfo(SoundComponentGlobalsPtr globals, SoundSource sourceID,
  178.                                  OSType selector, void *infoPtr)
  179. {
  180.     ComponentResult        result = noErr;
  181.  
  182.     switch (selector)
  183.     {
  184.         case siCompressionFactor:
  185.             GetCompressorInfo(infoPtr);                    // fill out the CompressionInfo structure passed in
  186.             break;
  187.  
  188.         default:
  189.             result = SoundComponentGetInfo(globals->sourceComponent, sourceID, selector, infoPtr);
  190.             break;
  191.     }
  192.  
  193.     return (result);
  194. }
  195.  
  196. /*    ==============================================================================
  197.     StopSource
  198.  
  199.     This routine is used to stop sounds that are currently playing. It should
  200.     clear out any internal buffers, reset any compression state information
  201.     and then delegate the call up the chain.
  202.  
  203.     NOTE: This can be called at interrupt time.
  204.     ============================================================================== */
  205.  
  206. pascal ComponentResult __SoundComponentStopSource(SoundComponentGlobalsPtr globals, short count, SoundSource *sources)
  207. {
  208.     globals->sourceDataPtr = nil;                        // clear out internal buffers
  209.     globals->thisComponent.sampleCount = 0;                // our buffer is empty
  210. #ifdef COMPRESSION
  211.     InitializeCompressor(globals);                        // initialize our compressor state
  212. #else
  213.     InitializeDecompressor(globals);                    // initialize our compressor state
  214. #endif
  215.     return (SoundComponentStopSource(globals->sourceComponent, count, sources));    // delegate this call
  216. }
  217.  
  218. /*    ==============================================================================
  219.     PlaySourceBuffer
  220.  
  221.     This routine is used to start a new sound playing. It should clear out any internal buffers
  222.     but should NOT reset any compression state information, since this could be a
  223.     continuation of a sound that has been broken into pieces. Then the call should be
  224.     delegated up the chain.
  225.  
  226.     NOTE: This can be called at interrupt time.
  227.     ============================================================================== */
  228.  
  229. pascal ComponentResult __SoundComponentPlaySourceBuffer(SoundComponentGlobalsPtr globals, SoundSource sourceID, SoundParamBlockPtr pb, long actions)
  230. {
  231.     globals->sourceDataPtr = nil;                        // clear out internal buffers
  232.     globals->thisComponent.sampleCount = 0;                // our buffer is empty
  233.  
  234.     return (SoundComponentPlaySourceBuffer(globals->sourceComponent, sourceID, pb, actions));    // delegate this call
  235. }
  236.  
  237.